package com.jml.config;

import com.jml.service.MyUserDetailsService;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

// 配置授权中心信息
@Configuration
@EnableAuthorizationServer // 开启认证授权中心
public class AuthorizationServerConfig2 extends AuthorizationServerConfigurerAdapter {

	@Autowired
	//@Qualifier("authenticationManagerBean")
	private AuthenticationManager authenticationManager;

	@Autowired
	@Qualifier("dataSource")
	private DataSource dataSource;

	 @Autowired
	 private MyUserDetailsService myUserDetailsService;

	/*@Autowired
	private RedisConnectionFactory connectionFactory;*/

	@Bean
	public TokenStore tokenStore() {

		// return new InMemoryTokenStore(); //使用内存存储token
		return new JdbcTokenStore(dataSource); /// 使用Jdbc存储token
		//也可以用redis存储  RedisTokenStore
		//new RedisTokenStore(connectionFactory);
	}

	//这个方法就是配置appid ，appkey，回调地址，token的有效期
	@Override
	public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
		// 添加授权用户
		clients.jdbc(dataSource);
				//下面代码注释掉，项目启动就是从数据库中读，
				//不注释掉项目启动就会从数据库中读，如果数据库中没有数据，就会报错
				//withClient里面是appid
				/* .inMemory().withClient("client_1")
				//secret里面的appkey或者appsecrity
		 		.secret(new BCryptPasswordEncoder().encode("123456"))
				// 允许授权范围-授权码模式,密码模式,刷新令牌
				.authorizedGrantTypes("password", "refresh_token", "authorization_code")
				// 返回授权码的地址
				.redirectUris("http://www.jml.com").authorities("ROLE_ADMIN", "ROLE_USER")
				//客户端可以使用的权限
				.scopes("all")
				//授权码有效时间
				.accessTokenValiditySeconds(7200).refreshTokenValiditySeconds(7200);*/
		// 自动往数据插入该应用id信息
	}

	@Override
	public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
		//从数据库中查
		endpoints.tokenStore(tokenStore())
				//刷新token需要加入下面两行
				.authenticationManager(authenticationManager)
				.userDetailsService(myUserDetailsService);// 必须设置
		// UserDetailsService
		// 否则刷新token 时会报错

		//写死的
		/*endpoints.authenticationManager(authenticationManager())
		 .allowedTokenEndpointRequestMethods(HttpMethod.GET,HttpMethod.POST);
		//刷新token需要加入下面两行
		endpoints.authenticationManager(authenticationManager());
		endpoints.userDetailsService(userDetailsService());*/
	}

	// 已经讲过UserDetailsService 写读数据
	/*@Bean
	UserDetailsService userDetailsService() {
		InMemoryUserDetailsManager userDetailsService = new InMemoryUserDetailsManager();
		userDetailsService.createUser(User.withUsername("user_1").password(new BCryptPasswordEncoder().encode("123456"))
				.authorities("ROLE_USER").build());
		userDetailsService.createUser(User.withUsername("user_2")
				.password(new BCryptPasswordEncoder().encode("1234567")).authorities("ROLE_USER").build());
		return userDetailsService;
	}*/

	@Override
	public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
		security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()")
				.allowFormAuthenticationForClients();// 允许表单登录

	}

	@Bean
	AuthenticationManager authenticationManager() {
		AuthenticationManager authenticationManager = new AuthenticationManager() {

			public Authentication authenticate(Authentication authentication) throws AuthenticationException {
				return daoAuhthenticationProvider().authenticate(authentication);
			}
		};
		return authenticationManager;
	}

	@Bean
	public AuthenticationProvider daoAuhthenticationProvider() {
		DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
		daoAuthenticationProvider.setUserDetailsService(myUserDetailsService);
		daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
		daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
		return daoAuthenticationProvider;
	}

	@Bean
	PasswordEncoder passwordEncoder() {
		// 加密方式
		PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
		return passwordEncoder;
	}
}
